package com.kaigejava.redis.controller;

import org.redisson.api.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author 凯哥Java
 * @description redisson 测试相关的
 * @company
 * @since 2022/11/1 22:34
 */
@RestController
public class RedissonController {

    @Resource
    private RedissonClient redissonClient;

    @Resource
    private RedisTemplate<String,String> redisTemplate;


    @GetMapping("/test")
    public String test(String msg){
        redisTemplate.opsForValue().set("ah","价格:"+msg);
        return "OK";
    }

    @GetMapping("/get-test")
    public String getTest(String key){
        return  redisTemplate.opsForValue().get(key);
    }

    /**
     * 可重入锁-没有设置超时时间的
     *
     * @return
     */
    @GetMapping("/reentrant-lock")
    public String reentrantLock() {
        //从Redison中获取锁
        RLock lock = redissonClient.getLock("my-lock");
        //加锁
        lock.lock();
        try {
            System.out.println("加锁成功，执行业务.... " + Thread.currentThread().getId());
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            System.out.println("操作业务失败");
        } finally {
            //手动解锁
            System.out.println("解锁..." + Thread.currentThread().getId());
            lock.unlock();
        }
        return "reentrant-lock";
    }


    /**
     * 可重入锁-有设置超时时间的
     *
     * @return
     */
    @GetMapping("/reentrant-lock-with-time")
    public String reentrantLockWithTime() {
        //从Redison中获取锁
        RLock lock = redissonClient.getLock("my-lock");
        //加锁
        lock.lock(5, TimeUnit.SECONDS);
        try {
            System.out.println("加锁成功，执行业务.... " + Thread.currentThread().getId());
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            System.out.println("操作业务失败");
        } finally {
            //手动解锁
            System.out.println("解锁..." + Thread.currentThread().getId());
            lock.unlock();
        }
        return "reentrant-lock-with-time";
    }


    /**
     * 读写锁
     *
     * @return
     */
    @GetMapping("/read-lock")
    public String readLock() {
        String s = "";
        //从Redison中获取锁
        RReadWriteLock lock = redissonClient.getReadWriteLock("my-lock");
        // 加写锁
        RLock rLock = lock.writeLock();
        try {
            //1、改数据加写锁，读数据加读锁
            rLock.lock();
            System.out.println("写锁加锁成功..." + Thread.currentThread().getId());
            s = UUID.randomUUID().toString();
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            System.out.println("操作业务失败");
        } finally {
            //手动解锁
            System.out.println("解锁..." + Thread.currentThread().getId());
            rLock.unlock();
        }
        return "获取写锁:" + s;
    }


    /**
     * 获取信号量：Semaphore
     *
     * @return
     */
    @GetMapping("/semaphore")
    public String semaphore() {
        RSemaphore semaphore = redissonClient.getSemaphore("semaphore");
        try {
            semaphore.acquire();
            //或
            semaphore.acquireAsync();
            semaphore.acquire(23);
            semaphore.tryAcquire();
            //或
            semaphore.tryAcquireAsync();
            semaphore.tryAcquire(23, TimeUnit.SECONDS);
            //或
            semaphore.tryAcquireAsync(23, TimeUnit.SECONDS);
            semaphore.release(10);
            semaphore.release();
            //或
            semaphore.releaseAsync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return semaphore.toString();
    }


    /**
     * 闭锁（CountDownLatch）
     * @return
     */
    @GetMapping("/countDownLatch")
    public String countDownLatch(){
        try {
            RCountDownLatch latch = redissonClient.getCountDownLatch("anyCountDownLatch");
            latch.trySetCount(1);
            latch.await();
            // 在其他线程或其他JVM里
            RCountDownLatch latch2 = redissonClient.getCountDownLatch("anyCountDownLatch");
            latch2.countDown();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "闭锁（CountDownLatch）";
    }
}
